package com.example.monthdateselector;

import hirondelle.date4j.DateTime;
import hirondelle.date4j.DateTime.DayOverflow;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.TimeZone;

import android.app.Activity;
import android.content.Context;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.GridView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends Activity {
	private GridView gridView1;
	private SelectorAdapter adapter;

	// private Point oldPoint;

	private boolean canScroll = true;

	private boolean hasMoved = false;

	private RangeTreeMap rangeMap = null;

	private boolean isInTheHead = false;
	private boolean isInTheTail = false;
	private TextView txtOverlay;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		View button1=findViewById(R.id.button1);
		button1.setBackgroundResource(R.drawable.report_cal_edit_head);
		button1.setBackgroundColor(Color.BLUE);
		
		gridView1 = (GridView) findViewById(R.id.gridView1);
		rangeMap = new RangeTreeMap();

		DateTime d = DateTime.today(TimeZone.getDefault());
		rangeMap.insert(new Range(d.minusDays(40), 6));
		rangeMap.insert(new Range(d.minusDays(15), 5));

		gridDataList = getCalDate();
		setRangeData(rangeMap);

		adapter = new SelectorAdapter(this, gridDataList);
		gridView1.setAdapter(adapter);
		gridView1.setOnTouchListener(new OnTouchListener() {

			@Override
			public boolean onTouch(View v, MotionEvent event) {
				String action = "";
				CalDayItem selectedItem = getViewCalDayItem(event.getX(), event.getY());

				switch (event.getAction()) {
				case MotionEvent.ACTION_DOWN:
					hasMoved = false;
					canScroll = true;
					if (editedRange != null) {
						// 在首尾点上
						if (selectedItem != null && selectedItem.getDate() != null) {
							isInTheHead = selectedItem.getDate().isSameDayAs(editedRange.getStart());
							isInTheTail = selectedItem.getDate().isSameDayAs(editedRange.getStart().plusDays(editedRange.getLength() - 1));// 为了点中绿色
							if (isInTheHead || isInTheTail) {
								canScroll = false;
							}
						}
					}

					break;
				case MotionEvent.ACTION_MOVE:
					hasMoved = true;
					action = "ACTION_MOVE";
					if (!canScroll) {

						CalDayItem selectedItem2 = getViewCalDayItem(event.getX(), event.getY());

						if (isInTheHead) {
							if (selectedItem2 != null && selectedItem2.getDate() != null && selectedItem2.getDate().lt(editedRange.getEnd())) { // 首尾
								// TODO 不能和其它的重叠

								editedRange.setStart(selectedItem2.getDate());
								setRangeData(rangeMap);
								adapter.notifyDataSetChanged();

							}
						} else if (isInTheTail) {
							if (selectedItem2 != null && selectedItem2.getDate() != null && selectedItem2.getDate().gt(editedRange.getStart())) {// 首尾
								// TODO 不能和其它的重叠

								editedRange.setEnd(selectedItem2.getDate().plusDays(1)); // 为了点中绿色
								setRangeData(rangeMap);
								adapter.notifyDataSetChanged();

							}
						}
					}
					break;
				case MotionEvent.ACTION_UP:
					canScroll = true;
					isInTheHead = false;
					isInTheTail = false;
					break;
				}
				return !canScroll;
			}

		});

		gridView1.setOnItemClickListener(new OnItemClickListener() {
			@Override
			public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
				if (!hasMoved) {
					CalDayItem cdi = adapter.getItem(arg2);
					DateTime startDate = cdi.getDate();
					if (cdi.getStatus() == SelectorAdapter.STATUS_NORMAL) {// 添加
						// 添加

						if (startDate != null) {
							// 是否会重叠
							Range r = new Range(startDate, default_select_len);
							DateTime end = r.getEnd();
							Range existsRange = getRangeHasTheDate(end, rangeMap);
							if (existsRange != null) {
								DateTime newEnd = existsRange.getStart().minusDays(1);
								Log.d("test", "end:" + newEnd.toString());
								Log.d("test", "startDate:" + startDate.toString());
								if (newEnd.lteq(startDate)) {
									return;
								} else {
									r.setEnd(newEnd);
								}
							}

							editedRange = r;
							rangeMap.insert(r);
							setRangeData(rangeMap);
							adapter.notifyDataSetChanged();
						}
					} else if (cdi.getStatus() >= SelectorAdapter.STATUS_SELECTED_HEAD && cdi.getStatus() <= SelectorAdapter.STATUS_SELECTED_TAIL) {// 选择状态变成编辑状态
						// 编辑

						editedRange = getRangeHasTheDate(startDate, rangeMap);
						setRangeData(rangeMap);
						adapter.notifyDataSetChanged();
					} else { // 其他,无反应
						// do nothing
					}

				}
			}
		});

		
		txtOverlay = (TextView) LayoutInflater.from(this).inflate(R.layout.popup_char_hint, null);
		txtOverlay.setVisibility(View.INVISIBLE);
		WindowManager.LayoutParams lp = new WindowManager.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.TYPE_APPLICATION,
				WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT);
		WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
		windowManager.addView(txtOverlay, lp);
		
		gridView1.setOnScrollListener(new OnScrollListener() {

			@Override
			public void onScrollStateChanged(AbsListView view, int scrollState) {
				if (scrollState == ListView.OnScrollListener.SCROLL_STATE_IDLE) { 
					txtOverlay.setVisibility(View.GONE);
				}else{
					txtOverlay.setVisibility(View.VISIBLE);
				}
			}

			@Override
			public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
				CalDayItem midderCDI=adapter.getItem(firstVisibleItem+visibleItemCount/2);
				if(midderCDI!=null&&midderCDI.getDate()!=null){
					CharSequence text=midderCDI.getDate().getMonth()+"月";
					txtOverlay.setText(text);
				}
			}
		});

	}

	private String getJsonString(DateTime d) {
		return d.getYear() + "-" + d.getMonth() + "-" + d.getDay();
	}

	/** 获得点击区域的Rang,如果没有返回null */
	private Range getRangeHasTheDate(DateTime d, RangeTreeMap rangeData) {
		for (Range range : rangeData.values()) {
			if (range.isInRange(d)) {
				return range;
			}
		}
		return null;
	}

	public void setRangeData(RangeTreeMap rangeData) {
		HashMap<String, CalDayItem> maps = new HashMap<String, CalDayItem>();
		for (CalDayItem cdi : gridDataList) {
			cdi.setStatus(SelectorAdapter.STATUS_NORMAL);
			if (cdi.getDate() != null) {
				maps.put(getJsonString(cdi.getDate()), cdi);
			}
		}

		for (Range range : rangeData.values()) {
			if (range.getStart() == null || range.getLength() == 0) {
				continue;
			} else {
				boolean isEditMode = range == editedRange;
				for (int i = 0; i < range.getLength(); i++) {
					CalDayItem cdi2 = maps.get(getJsonString(range.getStart().plusDays(i)));
					if (cdi2 != null) {
						int status = SelectorAdapter.STATUS_NORMAL;
						if (i == 0) {
							status = isEditMode ? SelectorAdapter.STATUS_EDITED_HEAD : SelectorAdapter.STATUS_SELECTED_HEAD;
						} else if (i == range.getLength() - 1) {
							status = isEditMode ? SelectorAdapter.STATUS_EDITED_TAIL : SelectorAdapter.STATUS_SELECTED_TAIL;
						} else {
							status = isEditMode ? SelectorAdapter.STATUS_EDITED_BODY : SelectorAdapter.STATUS_SELECTED_BODY;
						}
						cdi2.setStatus(status);
					}
				}
			}

		}
	}

	/** may be null */
	private Range editedRange = null;
	private int default_select_len = 7;
	public static final int Monthlen = 11;

	/** 日历 */
	private ArrayList<CalDayItem> getCalDate() {
		ArrayList<CalDayItem> gridDataList = new ArrayList<CalDayItem>();
		// 一年的日期数据(12个月)
		DateTime today = DateTime.today(TimeZone.getDefault());
		DateTime startDay = today.getStartOfMonth().minus(0, Monthlen, 0, 0, 0, 0, 0, DayOverflow.FirstDay);
		Log.d("test", startDay.toString());
		int firstEmptyLen = startDay.getWeekDay();
		for (int i = 1; i < firstEmptyLen; i++) {
			CalDayItem cell = new CalDayItem(null);
			cell.setStatus(SelectorAdapter.STATUS_EMPTY);
			gridDataList.add(cell);
		}

		DateTime endDay = today.getEndOfMonth();
		for (int i = 0, len = startDay.numDaysFrom(endDay); i <= len; i++) {
			DateTime item = startDay.plusDays(i);
			CalDayItem cell = new CalDayItem(item);
			gridDataList.add(cell);
		}

		return gridDataList;
	}

	/** 是否是真的移动(大于15才算移动) */
	private boolean isRealMove(Point oldPoint2, Point endPoint) {
		int disX = Math.abs(oldPoint2.x - endPoint.x);
		int disY = Math.abs(oldPoint2.y - endPoint.y);
		double dis = Math.sqrt(disY * disY + disX * disX);
		return dis > 15; // 大于15才算移动
	}

	private CalDayItem getViewCalDayItem(float x, float y) {
		CalDayItem cell = null;
		Log.d("test", "x:"+x+",y:"+y);
		int count = gridView1.getChildCount();
		for (int i = 0; i < count; i++) {
			View item = gridView1.getChildAt(i);
			if (null != item) {
				if (isPointOnTheView(x, y, item)) {
					cell = (CalDayItem) item.getTag();
					break;
				}
			}
		}
		Log.d("test", "cell:"+(cell==null?"is null":" is ok"));
		return cell;
	}

	/** 点p是否在View v上(范围内) */
	private boolean isPointOnTheView(float x, float y, View v) {
		Log.d("test", "view x:"+v.getX()+"view y:"+v.getY());
		return (y > v.getY()) && (y < v.getY() + v.getHeight()) && (x > v.getX()) && (x < v.getX() + v.getWidth());
	}

	private ArrayList<CalDayItem> gridDataList;

	public void doEdit(View v) {
		if (editedRange != null) {
			Toast.makeText(this, editedRange.toString(), Toast.LENGTH_SHORT).show();
			editedRange = null;
			setRangeData(rangeMap);
			adapter.notifyDataSetChanged();
		}
	}

}
